package com.piggy.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailAccount;
import cn.hutool.extra.mail.MailUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.aliyun.dysmsapi20170525.models.SendBatchSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendBatchSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.piggy.common.core.constant.Constants;
import com.piggy.common.core.exception.base.BaseException;
import com.piggy.common.core.utils.PageUtils;
import com.piggy.common.core.utils.sms.AliSendSmsUtils;
import com.piggy.common.core.utils.sms.SmsConfig;
import com.piggy.common.core.web.page.PagePlus;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.common.redis.service.RedisService;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.system.domain.SysSms;
import com.piggy.system.domain.bo.SysSmsAddBo;
import com.piggy.system.domain.bo.SysSmsBo;
import com.piggy.system.domain.bo.SysSmsEditBo;
import com.piggy.system.domain.bo.SysSmsQueryBo;
import com.piggy.system.domain.vo.SysSmsVo;
import com.piggy.system.mapper.SysSmsMapper;
import com.piggy.system.service.ISysConfigService;
import com.piggy.system.service.ISysSmsService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 消息模板Service业务层处理
 *
 * @author shark
 * @date 2021-08-16
 */
@Service
public class SysSmsServiceImpl extends ServiceImpl<SysSmsMapper, SysSms> implements ISysSmsService {
	@Autowired
	ISysConfigService configService;
	@Autowired
	private RedisService redisCache;

	@SneakyThrows
	@Override
	public Boolean sendSms(SysSmsBo bo) {
		//获取短信云配置
		SmsConfig cloudConfig = getConfig();
		//是否开启短信发送
		if (!cloudConfig.isOpenSend()) return true;

		com.aliyun.dysmsapi20170525.Client client = AliSendSmsUtils.createClient(cloudConfig.getAliyunAccessKeyId(),cloudConfig.getAliyunAccessKeySecret());
		SendSmsRequest sendReq = new SendSmsRequest()
			.setPhoneNumbers(bo.getPhoneNumber())
			.setTemplateCode(bo.getTemplateCode())
			.setSignName(bo.getSignName())
			.setTemplateParam(bo.getTemplateParam());

		//send
		SendSmsResponse sendResp = client.sendSms(sendReq);
		String code = sendResp.body.code;

		//database
		SysSms sms = new SysSms()
			.setAccessKeyId(cloudConfig.getAliyunAccessKeyId())
			.setAccessKeySecret(cloudConfig.getAliyunAccessKeySecret())
			.setCreateTime(new Date())
			.setLink(bo.getPhoneNumber())
			.setCreateBy(bo.getSendUserId())
			.setUserId(bo.getUserId())
			//0-站内信 1-邮件 2-短信
			.setType(bo.getType())
			.setSignName(bo.getSignName())
			.setStatus(StrUtil.compareIgnoreCase(code,"OK",false)==0?0:1)
			.setTemplateId(bo.getTemplateCode())
			.setSubject(bo.getSubject())
			.setSendResult(JSONUtil.toJsonStr(sendResp.body))
			.setParams(bo.getTemplateParam());

		validEntityBeforeSave(sms);

		//result
		if (!com.aliyun.teautil.Common.equalString(code, "OK")) {
			Console.error("错误信息: " + sendResp.body.message + "");
			return false;
		}
		return true;
	}

	@Override
	public Boolean autoCodeSendSms(String phone,String autoCode) {


		String tempParam="{\"code\":\""+autoCode+"\"}";

		SysSmsBo bo = new SysSmsBo()
			.setSubject("发送短信")
			.setType(2)
			.setUserId(1L)
			.setSendUserId(1L)
			.setSignName("中云融拓")
			.setTemplateCode("SMS_226786606")
			.setTemplateParam(tempParam)
			.setPhoneNumber(phone);
		this.sendSms(bo);

		return  true;

	}

	@Override
	public Boolean userRegSendSms(String phone) {

		int randomInt = RandomUtil.randomInt(1000, 10000);
		String tempParam="{\"code\":\""+randomInt+"\"}";

		SysSmsBo bo = new SysSmsBo()
			.setSubject("发送短信")
			.setType(2)
			.setUserId(1L)
			.setSignName("中云融拓")
			.setSendUserId(1L)
			.setTemplateCode("SMS_224435008")
			.setTemplateParam(tempParam)
			.setPhoneNumber(phone);
		this.sendSms(bo);

		// 保存验证码信息
		String verifyKey = Constants.REG_USER_SMS_KEY + phone;
		redisCache.setCacheObject(verifyKey, randomInt, Constants.REG_USER_SMS_EXPIRATION, TimeUnit.MINUTES);
		return  true;

	}

	@Override
	public SmsConfig getConfig() {
		String cloudConfig = configService.selectConfigByKey(Constants.ALICLOUDSMS);
		return JSON.parseObject(cloudConfig, SmsConfig.class);
	}

	@SneakyThrows
	@Override
	public Boolean sendBatchSms(List<SysSmsBo> smsList,String templateCode) {
		List<String> phoneNumbers = smsList.parallelStream().map(SysSmsBo::getPhoneNumber).collect(Collectors.toList());
		List<String> signNames = smsList.parallelStream().map(SysSmsBo::getSignName).collect(Collectors.toList());
		List<String> templateParams = smsList.parallelStream().map(SysSmsBo::getTemplateParam).collect(Collectors.toList());

		SmsConfig cloudConfig = getConfig();
		if (!cloudConfig.isOpenSend()) return true;
		com.aliyun.dysmsapi20170525.Client client = AliSendSmsUtils.createClient(cloudConfig.getAliyunAccessKeyId(),cloudConfig.getAliyunAccessKeySecret());
		SendBatchSmsRequest sendReq = new SendBatchSmsRequest()
			.setPhoneNumberJson(JSONUtil.toJsonStr(phoneNumbers))
			.setSignNameJson(JSONUtil.toJsonStr(signNames))
			.setTemplateCode(templateCode)
			.setTemplateParamJson(JSONUtil.toJsonStr(templateParams));

		SendBatchSmsResponse sendResp = client.sendBatchSms(sendReq);
		String code = sendResp.body.code;

		List<SysSms> sysSmsBos = new ArrayList<>();
		smsList.forEach(t->{
			//database
			SysSms sms = new SysSms()
				.setAccessKeyId(cloudConfig.getAliyunAccessKeyId())
				.setAccessKeySecret(cloudConfig.getAliyunAccessKeySecret())
				.setCreateTime(new Date())
				.setLink(t.getPhoneNumber())
				.setCreateBy(SecurityUtils.getUserId())
				.setUserId(t.getUserId())
				//0-站内信 1-邮件 2-短信
				.setType(t.getType())
				.setSignName(t.getSignName())
				.setStatus(StrUtil.compareIgnoreCase(code,"OK",false)==0?0:1)
				.setTemplateId(t.getTemplateCode())
				.setSubject(t.getSubject())
				.setSendResult(JSONUtil.toJsonStr(sendResp.body))
				.setParams(t.getTemplateParam());
			sysSmsBos.add(sms);
		});
		this.saveBatch(sysSmsBos);

		if (!com.aliyun.teautil.Common.equalString(code, "OK")) {
			Console.error("错误信息: " + sendResp.body.message + "");
			return false;
		}
		return true;
	}

	@SneakyThrows
	@Override
	public Boolean sendBatchSms(SysSmsBo bo) {
		SmsConfig cloudConfig = getConfig();
		if (!cloudConfig.isOpenSend()) return true;
		com.aliyun.dysmsapi20170525.Client client = AliSendSmsUtils.createClient(cloudConfig.getAliyunAccessKeyId(),cloudConfig.getAliyunAccessKeySecret());
		SendBatchSmsRequest sendReq = new SendBatchSmsRequest()
			.setPhoneNumberJson(JSONUtil.toJsonStr(bo.getPhoneNumbers()))
			.setSignNameJson(JSONUtil.toJsonStr(bo.getSignNames()))
			.setTemplateCode(bo.getTemplateCode())
			.setTemplateParamJson(JSONUtil.toJsonStr(bo.getTemplateParams()));

		SendBatchSmsResponse sendResp = client.sendBatchSms(sendReq);
		String code = sendResp.body.code;

		//database
		List<SysSms> sysSmsBos = new ArrayList<>();
		String sendResult = JSONUtil.toJsonStr(sendResp.body);
		for (int i = 0; i < bo.getPhoneNumbers().size(); i++) {
			SysSms sms = new SysSms()
				.setAccessKeyId(cloudConfig.getAliyunAccessKeyId())
				.setAccessKeySecret(cloudConfig.getAliyunAccessKeySecret())
				.setCreateTime(new Date())
				.setLink(bo.getPhoneNumbers().get(i))
				.setCreateBy(SecurityUtils.getUserId())
				.setUserId(bo.getUserId())
				//0-站内信 1-邮件 2-短信
				.setType(bo.getType())
				.setSignName(bo.getSignNames().get(i))
				.setStatus(StrUtil.compareIgnoreCase(code,"OK",false)==0?0:1)
				.setTemplateId(bo.getTemplateCode())
				.setSubject(bo.getSubject())
				.setSendResult(sendResult)
				.setParams(bo.getTemplateParams().get(i));
			sysSmsBos.add(sms);
		}
		this.saveBatch(sysSmsBos);

		if (!com.aliyun.teautil.Common.equalString(code, "OK")) {
			Console.error("错误信息: " + sendResp.body.message + "");
			return false;
		}
		return true;
	}


	@Override
    public SysSmsVo queryById(Long id){
        return getVoById(id, SysSmsVo.class);
    }

    @Override
    public TableDataInfo<SysSmsVo> queryPageList(SysSmsQueryBo bo) {
        PagePlus<SysSms, SysSmsVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo), SysSmsVo.class);
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<SysSmsVo> queryList(SysSmsQueryBo bo) {
        return listVo(buildQueryWrapper(bo), SysSmsVo.class);
    }

    private LambdaQueryWrapper<SysSms> buildQueryWrapper(SysSmsQueryBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<SysSms> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, SysSms::getUserId, bo.getUserId());
        lqw.eq(bo.getTemplateId() != null, SysSms::getTemplateId, bo.getTemplateId());
        lqw.eq(StrUtil.isNotBlank(bo.getLink()), SysSms::getLink, bo.getLink());
        lqw.eq(bo.getStatus() != null, SysSms::getStatus, bo.getStatus());
        lqw.eq(bo.getType() != null, SysSms::getType, bo.getType());
        lqw.eq(StrUtil.isNotBlank(bo.getAccessKeyId()), SysSms::getAccessKeyId, bo.getAccessKeyId());
        lqw.eq(StrUtil.isNotBlank(bo.getAccessKeySecret()), SysSms::getAccessKeySecret, bo.getAccessKeySecret());
		lqw.like(StrUtil.isNotBlank(bo.getSignName()), SysSms::getSignName, bo.getSignName());
        return lqw;
    }

    @Override
    public Boolean insertByAddBo(SysSmsAddBo bo) {
        SysSms add = BeanUtil.toBean(bo, SysSms.class);
        validEntityBeforeSave(add);
        return save(add);
    }

    @Override
    public Boolean updateByEditBo(SysSmsEditBo bo) {
        SysSms update = BeanUtil.toBean(bo, SysSms.class);
        validEntityBeforeSave(update);
        return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(SysSms entity){
        //TODO 做一些数据校验,如唯一约束
		this.save(entity);
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return removeByIds(ids);
    }
	@Override
	public Boolean sendMail(String content,String subject, List<String> params, String receiver) {

		String emailInfo = configService.selectConfigByKey(Constants.EMAILINFO);
		if(StrUtil.isBlank(emailInfo)){
			throw new BaseException("请联系管理员在系统配置中心配置邮箱信息！");
		}
		JSONObject emailJson = JSONUtil.parseObj(emailInfo);
		if (StrUtil.isBlankIfStr(emailJson.getStr("email")) || StrUtil.isBlankIfStr(emailJson.getStr("passWord"))) {
			throw new BaseException("请联系管理员在系统配置中心完善邮箱账号密码！");
		}
		String email = emailJson.getStr("email");
		String passWord = emailJson.getStr("passWord");


		//配置邮箱信息
		MailAccount account=new MailAccount();
		account.setHost("smtp.exmail.qq.com");
		account.setPort(465);
		account.setAuth(true);
		account.setSslEnable(true);
		account.setFrom(email);
		account.setUser(email);
		account.setPass(passWord);

		for(String param :params){
			content=StrUtil.format(content,param);
		}
		try{
			MailUtil.send(account, receiver, subject,content , true);
		}catch (Exception e){
			throw new BaseException("请联系平台管理员检查邮箱信息是否有效！");
		}

		SysSms sysSms=new SysSms();
		sysSms.setAccessKeyId(email)
				.setAccessKeyId(passWord)
				.setSubject(subject)
				.setLink(receiver)
				.setType(1)
				.setStatus(0)
				.setParams(params.toString())
				.setCreateBy(SecurityUtils.getUserId())
				.setSignName(subject);

		boolean save = save(sysSms);

		return save;
	}
}
